﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Reflection;

namespace QuanLyHocPhi.BLL
{
    /// <summary>
    /// Lớp chứa một số hàm tiện ích được mở rộng cho lớp List
    /// </summary>
    internal static class ListUtils
    {
        public static void Sort<TSource, TValue>(
            this List<TSource> source, Func<TSource, TValue> selector)
        {
            var comparer = Comparer<TValue>.Default;
            source.Sort((x, y) => comparer.Compare(selector(x), selector(y)));
        }

        public static void SortDescending<TSource, TValue>(
            this List<TSource> source, Func<TSource, TValue> selector)
        {
            var comparer = Comparer<TValue>.Default;
            source.Sort((x, y) => comparer.Compare(selector(y), selector(x)));
        }

        public static SortableBindingList<TSource> ToSortableBindingList<TSource>(this List<TSource> source)
        {
            return new SortableBindingList<TSource>(source);
        }
    }

    /// <summary>
    /// Lớp hỗ trợ bind dữ liệu + sắp xếp theo thuộc tính.
    /// Lớp này kế thừa từ BindingList&lt;T&rt; thay vì List&lt;T&rt; là để raise sự kiện
    /// khi có thay đổi nội dung của danh sách (chẳng hạn như khi thay đổi thuộc tính sắp xếp).
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class SortableBindingList<T> : BindingList<T>
    {
        #region Constructor
        public SortableBindingList(IList<T> list)
            : base(list) { } 
        #endregion

        #region Fields
        private bool m_IsSorted;
        private ListSortDirection m_SortDirection;
        private PropertyDescriptor m_SortProperty; 
        #endregion

        #region Properties
        protected override ListSortDirection SortDirectionCore { get { return m_SortDirection; } }
        protected override PropertyDescriptor SortPropertyCore { get { return m_SortProperty; } }
        protected override bool IsSortedCore { get { return m_IsSorted; } }
        protected override bool SupportsSortingCore { get { return true; } } 
        #endregion

        #region Methods
        protected override void RemoveSortCore() { m_IsSorted = false; }
        protected override void ApplySortCore(PropertyDescriptor propertyDescriptor, ListSortDirection direction)
        {
            //if (propertyDescriptor.PropertyType.GetInterface("IComparable") == null)
            //    return;
            var list = this.Items as List<T>;
            if (list == null)
            {
                m_IsSorted = false;
            }
            else
            {
                var comparer = new PropertyComparer(propertyDescriptor.Name, direction);
                list.Sort(comparer);
                m_IsSorted = true;
                m_SortDirection = direction;
                m_SortProperty = propertyDescriptor;
            }
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        } 
        #endregion

        // sub class
        public class PropertyComparer : IComparer<T>
        {
            // thuộc tính
            private PropertyInfo PropInfo { get; set; }
            private ListSortDirection Direction { get; set; }

            // hàm khởi dựng
            public PropertyComparer(string propName, ListSortDirection direction)
            {
                this.PropInfo = typeof(T).GetProperty(propName);
                this.Direction = direction;
            }

            // methods
            public int Compare(T x, T y)
            {
                var _X = PropInfo.GetValue(x, null);
                var _Y = PropInfo.GetValue(y, null);
                if (Direction == ListSortDirection.Ascending)
                    return Comparer.Default.Compare(_X, _Y);
                else
                    return Comparer.Default.Compare(_Y, _X);
            }
        }
    }
}
